const express = require("express");
const fs = require("fs");
const path = require("path");
const Handlebars = require("handlebars");
const markdownIt = require("markdown-it");
const uuid = require('uuid');

// 初始化 markdown 解析器
const md = new markdownIt();

// 目录路径
const inputDir = "./source";
const templatePath = "./template/layout.hbs";

// 读取所有的 .md 文件
const readFiles = () => {
  return new Promise((resolve, reject) => {
    fs.readdir(inputDir, (err, files) => {
      if (err) return reject(err);
      resolve(files.filter((file) => path.extname(file) === ".md"));
    });
  });
};

// 更新 db.json 文件
const updateDbJson = async (newFiles, inputDir) => {
  try {
    const jsonData = await fs.promises.readFile('./db.json', 'utf8');
    const data = JSON.parse(jsonData);

    // 获取当前文件名集合
    const currentFileNames = new Set(data.files.map(file => file.name));
    const newFileNames = new Set(newFiles.map(file => file.name));

    // 创建一个映射表，以便快速查找现有文件
    const existingFilesMap = new Map(data.files.map(file => [file.name, file]));

    // 删除已删除的文件记录
    const deletedFiles = [...currentFileNames].filter(name => !newFileNames.has(name));
    deletedFiles.forEach(name => {
      data.files = data.files.filter(file => file.name !== name);
    });

    // 更新已存在的文件记录，并添加新文件记录
    const updatedFiles = newFiles.map(file => {
      if (existingFilesMap.has(file)) {
        // 如果文件已存在，则保留原有记录
        return existingFilesMap.get(file);
      } else {
        // 如果文件是新增的，则生成新的记录
        const fileId = uuid.v4(); // 生成唯一ID
        return {
          id: fileId,
          name: file,
        };
      }
    });

    // 替换文件列表
    data.files = updatedFiles;

    // 写入新的db.json文件
    await fs.promises.writeFile('./db.json', JSON.stringify(data, null, 2), 'utf8');
    console.log('Files have been updated in db.json');
  } catch (error) {
    console.error('Error:', error);
  }
};

// 从 .md 文件中提取标题
const extractTitles = (files) => {
  return Promise.all(
    files.map(async (file) => {
      const filePath = path.join(inputDir, file);
      const data = await fs.promises.readFile(filePath, "utf8");
      const lines = data.split("\n");
      let title = "";
      for (let line of lines) {
        if (line.startsWith("# ")) {
          title = line.slice(2).trim();
          break;
        }
      }
      return { filename: file, title };
    })
  );
};

// 创建 Express 应用
const app = express();
const port = 3000;

// 静态文件中间件
app.use("/assets", express.static(path.join(__dirname, "assets")));

// 主路由
app.get("/", async (req, res) => {
  try {
    const jsonData = require('./db.json')
    const files = await readFiles();
    let fileName;
    // 更新 db.json 文件
    await updateDbJson(files, inputDir);
    console.log(req.query)
    console.log(jsonData.files)
    if(req.query.id){
      fileName = jsonData.files.find(item => item.id == req.query.id)?.name;
    } else {
      fileName = files[0];
    } 
    console.log(fileName)

    if (!fileName) {
      return res.status(404).send("No Markdown files found.");
    }

    const filePath = path.join(inputDir, fileName); // 获取文件

    const data = await fs.promises.readFile(filePath, "utf8");
    const html = md.render(data);
    const postTitle = (await extractTitles([fileName]))[0].title;

    const _html = html
      .replace(/&/g, "&amp;")
      .replace(/</g, "&lt;")
      .replace(/>/g, "&gt;")
      .replace(/"/g, "&quot;")
      .replace(/'/g, "&#039;");

    const _style = `<style>
      /* 在子页面中设置滚动条样式 */
      ::-webkit-scrollbar {
        width: 10px; /* 滚动条宽度 */
      }
      ::-webkit-scrollbar-track {
        background: #e0e0e0; /* 滚动条轨道颜色 */
      }
      ::-webkit-scrollbar-thumb {
        background: #999999; /* 滚动条滑块颜色 */
      }
      ::-webkit-scrollbar-thumb:hover {
        background: #777777; /* 滚动条滑块悬停颜色 */
      }
      pre{
        background-color: #1e293b;
        color: #f8fafc;
        padding:20px;
      }
    </style>`;

    const context = { title: postTitle, content: _html + _style };
    console.log("context", context);
    // 读取模板文件
    const source = fs.readFileSync(templatePath, "utf8");
    const template = Handlebars.compile(source);

    // 渲染并发送 HTML 文件
    const renderedHtml = template(context);
    res.send(renderedHtml);
  } catch (error) {
    console.error(error);
    res.status(500).send("An error occurred.");
  }
});


app.get("/files", async (req, res) => {
  try {
    const jsonData = require('./db.json')
      res.send({
        code:200,
        data:jsonData.files
      });
  } catch (error) {
    console.error(error);
    res.status(500).send("server error");
  }
})


// 启动服务器
app.listen(port, () => {
  console.log(`Server running on http://localhost:${port}`);
});
